package com.zhitan.ems.oss.service;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.zhitan.ems.oss.config.AliyunOssProperties;
import cn.hutool.core.util.StrUtil;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 阿里云OSS文件存储服务实现
 * 
 * @author zhitan
 */
@ConditionalOnProperty(name = "oss.aliyun.enabled", havingValue = "true")
@Service("aliyunOssFileStorageService")
public class AliyunOssFileStorageService extends AbstractFileStorageService {
    
    private final AliyunOssProperties aliyunOssProperties;
    private final OSS ossClient;
    
    public AliyunOssFileStorageService(AliyunOssProperties aliyunOssProperties) {
        this.aliyunOssProperties = aliyunOssProperties;
        // 只有在配置了有效的AccessKey时才初始化OSS客户端
        if (StrUtil.isNotEmpty(aliyunOssProperties.getAccessKeyId()) && 
            StrUtil.isNotEmpty(aliyunOssProperties.getAccessKeySecret())) {
            this.ossClient = new OSSClientBuilder().build(
                    aliyunOssProperties.getEndpoint(),
                    aliyunOssProperties.getAccessKeyId(),
                    aliyunOssProperties.getAccessKeySecret());
        } else {
            this.ossClient = null;
        }
    }
    
    @Override
    public String uploadFile(MultipartFile file) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        validateFileSize(file);
        String originalFilename = file.getOriginalFilename();
        String fileName = generateFileName(originalFilename);
        try {
            return uploadFile(file.getInputStream(), fileName, file.getContentType());
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    @Override
    public String uploadFile(MultipartFile file, String fileName) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        try {
            return uploadFile(file.getInputStream(), fileName, file.getContentType());
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        }
    }
    
    @Override
    public String uploadFile(InputStream inputStream, String fileName, String contentType) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        try {
            validateFileSize(inputStream);
            String filePath = buildFilePath(aliyunOssProperties.getPrefix(), fileName);
            
            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                    aliyunOssProperties.getBucketName(), 
                    filePath, 
                    inputStream);
            
            // 设置文件类型
            ObjectMetadata metadata = new ObjectMetadata();
            if (StrUtil.isNotEmpty(contentType)) {
                metadata.setContentType(contentType);
            }
            putObjectRequest.setMetadata(metadata);
            
            // 上传文件
            ossClient.putObject(putObjectRequest);
            
            return getFileUrl(filePath);
        } catch (IOException e) {
            throw new RuntimeException("文件上传失败", e);
        } catch (Exception e) {
            throw new RuntimeException("阿里云OSS上传失败", e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                // 忽略关闭异常
            }
        }
    }
    
    @Override
    public boolean deleteFile(String filePath) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        try {
            // 移除URL前缀
            String realPath = removeUrlPrefix(filePath);
            ossClient.deleteObject(aliyunOssProperties.getBucketName(), realPath);
            return true;
        } catch (Exception e) {
            throw new RuntimeException("文件删除失败", e);
        }
    }
    
    @Override
    public Map<String, Object> getFileInfo(String filePath) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        try {
            // 移除URL前缀
            String realPath = removeUrlPrefix(filePath);
            ObjectMetadata metadata = ossClient.getObjectMetadata(
                    aliyunOssProperties.getBucketName(), 
                    realPath);
            
            Map<String, Object> fileInfo = new HashMap<>();
            fileInfo.put("path", filePath);
            fileInfo.put("name", realPath.substring(realPath.lastIndexOf('/') + 1));
            fileInfo.put("size", metadata.getContentLength());
            fileInfo.put("type", metadata.getContentType());
            fileInfo.put("ext", getFileExtension(realPath));
            fileInfo.put("storageType", getStorageType());
            fileInfo.put("createTime", metadata.getLastModified().getTime());
            
            // 添加阿里云OSS特有信息
            fileInfo.put("etag", metadata.getETag());
            fileInfo.put("bucket", aliyunOssProperties.getBucketName());
            
            return fileInfo;
        } catch (Exception e) {
            throw new RuntimeException("获取文件信息失败", e);
        }
    }
    
    @Override
    public InputStream downloadFile(String filePath) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        try {
            // 移除URL前缀
            String realPath = removeUrlPrefix(filePath);
            OSSObject ossObject = ossClient.getObject(
                    aliyunOssProperties.getBucketName(), 
                    realPath);
            return ossObject.getObjectContent();
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }
    
    @Override
    public String getFileUrl(String filePath) {
        if (ossClient == null) {
            throw new RuntimeException("阿里云OSS客户端未正确初始化，请检查配置");
        }
        if (StrUtil.isNotEmpty(aliyunOssProperties.getDomain())) {
            String protocol = aliyunOssProperties.isHttps() ? "https://" : "http://";
            return protocol + aliyunOssProperties.getDomain() + "/" + filePath;
        }
        
        // 生成带签名的临时URL（有效期10年）
        Date expiration = new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(365 * 10));
        URL url = ossClient.generatePresignedUrl(
                aliyunOssProperties.getBucketName(), 
                filePath, 
                expiration);
        
        return url.toString();
    }
    
    @Override
    public String getStorageType() {
        return "aliyun";
    }
    
    /**
     * 移除URL前缀
     */
    private String removeUrlPrefix(String filePath) {
        if (StrUtil.isEmpty(filePath)) {
            return filePath;
        }
        
        // 移除协议和域名部分
        if (filePath.contains("://")) {
            int startIndex = filePath.indexOf("://") + 3;
            int endIndex = filePath.indexOf('/', startIndex);
            if (endIndex > 0) {
                return filePath.substring(endIndex + 1);
            }
        }
        
        // 移除bucket域名
        String bucketDomain = aliyunOssProperties.getBucketName() + "." + aliyunOssProperties.getEndpoint();
        if (filePath.contains(bucketDomain)) {
            int startIndex = filePath.indexOf(bucketDomain) + bucketDomain.length();
            if (startIndex < filePath.length()) {
                return filePath.substring(startIndex).replaceFirst("^/", "");
            }
        }
        
        return filePath;
    }
}